package org.flyframework.dnd
{
	import mx.core.IUIComponent;
	import mx.events.DragEvent;
	import mx.managers.DragManager;
	
	import org.flyframework.Fly;
	
	/**
	 * Droppable...
	 * 
	 * @author Ben Edwards
	 */
	public class Droppable
	{
		
		protected var target:IUIComponent;
		
		protected var acceptFunction:Function = defaultAcceptFunction;
		protected var feedbackFunction:Function = defaultFeedbackFunction;
		
		protected var ifFormats:Array = new Array();
		
		
		//--------------------------------------------------------------------------
		// Init
		//--------------------------------------------------------------------------
		
		public function Droppable( component:IUIComponent )
		{
			this.target = component;
			
			// a dragEnter event occurs when a draggable is over a droppable
			this.target.addEventListener( DragEvent.DRAG_ENTER, _dragEnter );
			// a dragOver event occurs when a draggable is over a droppable (accepted)
			this.target.addEventListener( DragEvent.DRAG_OVER, _dragOver );
		}
		
		
		//--------------------------------------------------------------------------
		// Callables
		//--------------------------------------------------------------------------
		
		public function accept( acceptFunction:Function ):Droppable
		{
			this.acceptFunction = acceptFunction;
			
			return this;
		}
		
		public function feedback( feedbackFunction:Function ):Droppable
		{
			this.feedbackFunction = feedbackFunction;
			
			return this;
		}
		
		public function ifFormat( format:String ):Droppable
		{
			this.ifFormats.push( format );
			
			return this;
		}
		
		public function dragEnter( enterFunction:Function, flags:uint=0 ):Droppable
		{
			// a dragEnter event occurs when a draggable is over a droppable
			//this.target.addEventListener( DragEvent.DRAG_ENTER, enterFunction );
			Fly.addListener( this.target, DragEvent.DRAG_ENTER, enterFunction );
			
			return this;
		}
		
		
		public function dragExit( exitFunction:Function, flags:uint=0 ):Droppable
		{
			// a dragExit event occurs when...
			//this.target.addEventListener( DragEvent.DRAG_EXIT, exitFunction );
			Fly.addListener( this.target, DragEvent.DRAG_ENTER, exitFunction, flags );
			
			return this;
		}
		
		public function dragOver( overFunction:Function, flags:uint=0 ):Droppable
		{
			// a dragOver event occurs when a draggable is over a droppable (accepted)
			//this.target.addEventListener( DragEvent.DRAG_OVER, overFunction );
			Fly.addListener( this.target, DragEvent.DRAG_ENTER, overFunction, flags );
			
			return this;
		}
		
		public function dragDrop( dropFunction:Function, flags:uint=0 ):Droppable
		{
			// a dragDrop event occurs when a draggable is dropped
			//this.target.addEventListener( DragEvent.DRAG_DROP, dropFunction );
			Fly.addListener( this.target, DragEvent.DRAG_DROP, dropFunction, flags );
			
			return this;
		}
		
		
		//--------------------------------------------------------------------------
		// Event Handlers
		//--------------------------------------------------------------------------
		
		protected function _dragEnter( dragEvent:DragEvent ):void
		{
			// TODO: this isn't quite right, it should ask an allowFunction or just call the accept function
			if( this.acceptFunction(dragEvent) )
			{
//				DragManager.acceptDragDrop( dragEvent.dragInitiator );
				var dropTarget:IUIComponent = dragEvent.currentTarget as IUIComponent;
				DragManager.acceptDragDrop( dropTarget );
				
				DragManager.showFeedback( this.feedbackFunction(dragEvent) );
			}
		}
		
		protected function _dragOver( dragEvent:DragEvent ):void
		{
			DragManager.showFeedback( this.feedbackFunction(dragEvent) );
		}
		
		
		//--------------------------------------------------------------------------
		// Default Functions
		//--------------------------------------------------------------------------
		
		protected function defaultAcceptFunction( dragEvent:DragEvent ):Boolean
		{
			if( hasRequiredFormat(dragEvent) )
			{
				//DragManager.acceptDragDrop( dragEvent.currentTarget as IUIComponent );
				DragManager.acceptDragDrop( dragEvent.dragInitiator );
				
				return true;
			}
			return false;
		}
		
		protected function hasRequiredFormat( dragEvent:DragEvent ):Boolean
		{
			if( this.ifFormats.length == 0 )
			{
				// no required formats
				return true;
			}
			
			var format:String;
			for each( format in this.ifFormats )
			{
				if( dragEvent.dragSource.hasFormat(format) )
				{
					// required format found
					return true;
				}
			}
			
			// required format not found
			return false;
		}
		
		protected function defaultFeedbackFunction( dragEvent:DragEvent ):String
		{
			return DragManager.NONE;
		}
		
	}
}